package com.tencreat.service.system.impl;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.bean.BeanUtil;
import com.tencreat.common.annotation.DictName;
import com.tencreat.common.core.domain.entity.SysDictData;
import com.tencreat.common.core.domain.entity.SysDictType;
import com.tencreat.common.utils.DictUtils;
import com.tencreat.mapper.system.SysDictDataMapper;
import com.tencreat.mapper.system.SysDictTypeMapper;
import com.tencreat.service.system.ISysDictDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 字典 业务层处理
 *
 * @Company: 深圳腾创互联科技有限公司
 * @link: https://tencreat.com/#/
 * @author tencreat
 */
@Service
public class SysDictDataServiceImpl implements ISysDictDataService
{
    @Autowired
    private SysDictDataMapper dictDataMapper;

    @Autowired
    private SysDictTypeMapper dictTypeMapper;

    /**
     * 根据条件分页查询字典数据
     *
     * @param dictData 字典数据信息
     * @return 字典数据集合信息
     */
    @Override
    public List<SysDictData> selectDictDataList(SysDictData dictData)
    {
        List<SysDictData> sysDictData = dictDataMapper.selectDictDataList(dictData);
        reloadCache();
        return sysDictData;
    }

    public void reloadCache(){
        List<SysDictType> sysDictTypes = dictTypeMapper.selectDictTypeAll();
        for (SysDictType dictTypes : sysDictTypes)
        {
            List<SysDictData> dictData = dictDataMapper.selectDictDataByType(dictTypes.getDictType());
            DictUtils.setDictCache(dictTypes.getDictType(), dictData);
        }
    }

    /**
     * 根据字典类型和字典键值查询字典数据信息
     *
     * @param dictType 字典类型
     * @param dictValue 字典键值
     * @return 字典标签
     */
    @Override
    public String selectDictLabel(String dictType, String dictValue)
    {
        String label = dictDataMapper.selectDictLabel(dictType, dictValue);
        reloadCache();
        return label;
    }

    /**
     * 根据字典数据ID查询信息
     *
     * @param dictCode 字典数据ID
     * @return 字典数据
     */
    @Override
    public SysDictData selectDictDataById(Long dictCode)
    {
        return dictDataMapper.selectDictDataById(dictCode);
    }

    /**
     * 批量删除字典数据信息
     *
     * @param dictCodes 需要删除的字典数据ID
     * @return 结果
     */
    @Override
    public int deleteDictDataByIds(Long[] dictCodes)
    {
        SysDictData sysDictData = dictDataMapper.selectDictDataById(dictCodes[0]);
        int row = dictDataMapper.deleteDictDataByIds(dictCodes);
        if (row > 0)
        {
            DictUtils.clearDictCache(sysDictData.getDictType());
        }
        return row;
    }

    /**
     * 新增保存字典数据信息
     *
     * @param dictData 字典数据信息
     * @return 结果
     */
    @Override
    public int insertDictData(SysDictData dictData)
    {
        int row = dictDataMapper.insertDictData(dictData);
        if (row > 0)
        {
            DictUtils.clearDictCache(dictData.getDictType());
        }
        return row;
    }

    /**
     * 修改保存字典数据信息
     *
     * @param dictData 字典数据信息
     * @return 结果
     */
    @Override
    public int updateDictData(SysDictData dictData)
    {
        int row = dictDataMapper.updateDictData(dictData);
        if (row > 0)
        {
            DictUtils.clearDictCache(dictData.getDictType());
        }
        return row;
    }

    @Override
    public int updateByCode(String dictValue, Integer dictCode) {
        int row = dictDataMapper.updateByCode(dictValue,dictCode);
        if (row > 0)
        {
            DictUtils.clearDictCache();
        }
        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDictData(List<SysDictData> dictData) {
        dictData.forEach(item -> dictDataMapper.updateDictData(item));
        DictUtils.clearDictCache();
        return 1;
    }

    @Override
    public <T> void updateObjectData(T data) {
        Class<?> clazz = data.getClass();
        Object dictName = AnnotationUtil.getAnnotationValue(clazz, DictName.class);
        if (dictName == null) {
            dictName = clazz.getSimpleName();
        }
        Field[] fields = clazz.getDeclaredFields();
        List<SysDictData> newSysDictDataList = new ArrayList<>();
        List<SysDictData> oldSysDictDataList = DictUtils.getDictCache(dictName.toString());
        if (null != oldSysDictDataList) {
            for (SysDictData sysDictData : oldSysDictDataList) {
                for (Field field : fields) {
                    Object value =  BeanUtil.getFieldValue(data, field.getName());
                    if (value != null) {
                        String fieldName = field.getName();
                        if (fieldName.equals(sysDictData.getDictLabel())) {
                            sysDictData.setDictValue(value.toString());
                            dictDataMapper.updateDataByLabel(dictName.toString(), field.getName(), value.toString());
                        }
                    }
                }
                newSysDictDataList.add(sysDictData);
            }
        }
        if (newSysDictDataList.size() > 0) {
            DictUtils.setDictCache(dictName.toString(), newSysDictDataList);
        }
    }

    @Override
    public <T> T getObjectData(Class<T> clazz) {
        Object dictName = AnnotationUtil.getAnnotationValue(clazz, DictName.class);
        if (dictName == null) {
            dictName = clazz.getSimpleName();
        }
        List<SysDictData> sysDictData = DictUtils.getDictCache(dictName.toString());
        try {
            T object = clazz.newInstance();
            if (sysDictData != null) {
                Field[] fields = clazz.getDeclaredFields();
                if (fields.length > 0) {
                    List<String> fieldNames = Arrays.stream(fields).map(Field::getName).collect(Collectors.toList());
                    for (SysDictData i : sysDictData) {
                        if (fieldNames.contains(i.getDictLabel())) {
                            BeanUtil.setFieldValue(object, i.getDictLabel(), i.getDictValue());
                        }
                    }
                    return object;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new RuntimeException("获取字典"+ dictName +"失败");
    }

    @Override
    public List<Map<String, String>> getObjectDataByType(String dictType) {
        List<SysDictData> sysDictData = DictUtils.getDictCache(dictType);
        List<Map<String, String>> list = new ArrayList<>();
        try {
            if (sysDictData != null) {
                for (SysDictData i : sysDictData) {
                    Map<String, String> map = new HashMap<>();
                    map.put("label", i.getDictLabel());
                    map.put("value", i.getDictValue());
                    list.add(map);
                }
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new RuntimeException("获取字典"+ dictType +"失败");
    }

}
